package com.zoe.onelink.core.property;

import com.zoe.onelink.core.property.http.HttpClientConfig;
import com.zoe.onelink.core.property.http.RestTemplateConfig;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-09-08
 */
@Data
@ConfigurationProperties(prefix = "onelink")
public class OnelinkProperties {

    private Common common = new Common();

    private Web web = new Web();

    private Http http = new Http();

    /**
     * 通用参数
     */
    @Data
    public static class Common {

        /**
         * 异常堆栈数量阈值,超过该阈值自动裁剪
         */
        private int stackTraceThreshold = 30;

        /**
         * 隐藏异常具体详情
         */
        private boolean muteExceptionError = false;

    }

    /**
     * Web参数
     */
    @Data
    public static class Web {

        /**
         * 翻译@Valid验证结果
         */
        private boolean translateValidation = false;

        private Response response = new Response();

        private Arg requestArg = new Arg();

        private Encrypt encrypt = new Encrypt();

        @Data
        public static class Response {
            /**
             * 返回结果包装器,默认启用
             */
            private boolean wrapped = true;
            /**
             * 返回结果字段为null自动填充为空字符串
             */
            private boolean nullToEmpty = false;
            /**
             * 默认为空则填充所有类型. 例: string,integer,date
             */
            private List<Type> nullToEmptyTypes = List.of(Type.OBJECT);

            @Getter
            @AllArgsConstructor
            public enum Type {
                STRING(String.class),
                NUMBER(Number.class),
                BOOLEAN(Boolean.class),
                DATE(Date.class),
                ARRAY(Array.class),
                MAP(Map.class),
                COLLECTION(Collection.class),
                // 针对所有类型生效
                OBJECT(Object.class);
                private Class<?> value;
            }
        }

        @Data
        public static class Arg {
            /**
             * application/json 方式入参增强,默认不启用
             */
            private boolean enabled = false;
            /**
             * 注解策略
             */
            private AnnotationStrategy annotationStrategy = AnnotationStrategy.ONLY_ANNOTATED;

            /**
             * 扁平化覆盖策略
             */
            private FlattenOverwriteStrategy flattenOverwriteStrategy = FlattenOverwriteStrategy.NOT_OVERWRITE;

            /**
             * 扁平化请求参数(用于兼容旧项目)
             */
            private boolean flatten = false;

            /**
             * 自动将参数应用于嵌套对象里面的字段
             */
            private boolean autoFillNested = false;

            /**
             * {@link com.zoe.onelink.annotation.web.arg.RequestArg} 策略
             */
            public enum AnnotationStrategy {
                /**
                 * 即便没有手动标记@RequestArg注解,也会对所有入参都生效 (用于兼容旧项目parameter写法)
                 */
                APPLY_TO_ALL,
                /**
                 * 只有在方法上或者方法入参中手动标记@RequestArg注解才生效
                 */
                ONLY_ANNOTATED,
            }

            /**
             * 扁平化值覆盖策略
             */
            public enum FlattenOverwriteStrategy {
                /**
                 * 不覆盖
                 */
                NOT_OVERWRITE,
                /**
                 * 总是覆盖
                 */
                ALWAYS_OVERWRITE,
                /**
                 * 如果Key重复,抛出异常
                 */
                THROW_IF_KEY_REPEAT,
                /**
                 * 如果key重名,自动在key前面加上下划线"_",加完下划线还重名的话,抛出异常
                 */
                UNDERLINE_IF_KEY_REPEAT
            }

        }

        @Data
        public static class Encrypt {

            /**
             * 字段加密功能全局开关
             */
            private boolean enabled = true;

            /**
             * 密钥
             */
            private Map<String, EncryptKeyPair> keyPairs = new HashMap<>();

        }


    }

    @Data
    public static class Http {

        /**
         * 第三方请求工具类连接配置
         */
        @NestedConfigurationProperty
        private HttpClientConfig httpClient = new HttpClientConfig();

        /**
         * RestTemplate配置
         */
        @NestedConfigurationProperty
        private RestTemplateConfig restTemplate = new RestTemplateConfig();

    }

}
